/* Copyright 2012 Guewen Baconnier (Camptocamp SA)
   Copyright 2016 Antonio Espinosa <antonio.espinosa@tecnativa.com>
 * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */

odoo.define("web_translate_dialog.translate_dialog", function(require) {
    "use strict";

    var core = require("web.core");
    var BasicController = require("web.BasicController");
    var data = require("web.data");
    var Context = require("web.Context");
    var concurrency = require("web.concurrency");
    var Dialog = require("web.Dialog");
    var session = require("web.session");
    var rpc = require("web.rpc");
    var FormController = require("web.FormController");
    var _t = core._t;
    var QWeb = core.qweb;
    var Mutex = concurrency.Mutex;

    var TranslateDialog = Dialog.extend({
        template: "TranslateDialog",
        init: function(parent, options) {
            var title_string = _t("Translate fields: /");
            var field_names = {};
            var single_field = false;
            if (options.field) {
                this.record_id = options.field.id;
                var record = parent.model.get(options.field.id);
                this.model = record.model;
                field_names[options.field.fieldName] =
                    record.fields[options.field.fieldName];
                single_field = true;
                title_string = title_string.replace(
                    "/",
                    record.fields[options.field.fieldName].string
                );
            } else {
                this.record_id = parent.handle;
                this.model = parent.modelName;
                field_names = this.get_translatable_fields(parent);
            }
            this._super(parent, {title: title_string, size: "x-large"});
            this.view_language = session.user_context.lang;
            this.view = parent;
            this.view_type = parent.viewType || "";
            this.translatable_fields = field_names;
            this.res_id = options.res_id;
            this.single_field = single_field;
            this.languages = null;
            this.languages_loaded = $.Deferred();
            this.lang_data = new data.DataSetSearch(this, "res.lang", parent.context, [
                ["active", "=", "1"],
            ]);
            this.lang_data.set_sort(["tr_sequence asc", "id asc"]);
            this.lang_data.read_slice(["code", "name"]).then(this.on_languages_loaded);
        },
        willStart: function() {
            var self = this;
            return this._super.apply(this, arguments).then(function() {
                if (self.size === "x-large") {
                    self.$modal.find(".modal-dialog").addClass("modal-xl");
                }
            });
        },
        get_translatable_fields: function(parent) {
            var field_list = {};
            _.each(parent.renderer.state.fields, function(field, name) {
                var related_readonly =
                    typeof field.related !== "undefined" && field.readonly;
                if (
                    field.translate === true &&
                    !related_readonly &&
                    parent.renderer.state.getFieldNames().includes(name)
                ) {
                    field_list[name] = field;
                }
            });
            return field_list;
        },
        on_languages_loaded: function(langs) {
            this.languages = langs;
            this.languages_loaded.resolve();
        },
        open: function() {
            // The template needs the languages
            return $.when(this.languages_loaded).then($.proxy(this._super, this));
        },
        start: function() {
            var self = this;
            this.$(".oe_translation_field").change(function() {
                $(this).toggleClass(
                    "touched",
                    $(this).val() !== $(this).attr("data-value")
                );
            });
            this.$footer.html(QWeb.render("TranslateDialog.buttons"));
            this.$footer
                .find(".oe_form_translate_dialog_save_button")
                .click(function() {
                    self.on_button_save();
                    self.on_button_close();
                });
            this.$footer
                .find(".oe_form_translate_dialog_cancel_button")
                .click(function() {
                    self.on_button_close();
                });

            this.do_load_fields_values();
        },
        resize_textareas: function() {
            var textareas = this.$("textarea.oe_translation_field");
            var max_height = 100;
            // Resize textarea either to the max height of its content if it stays
            // in the modal or to the max height available in the modal
            if (textareas.length) {
                _.each(textareas, function(textarea) {
                    if (textarea.scrollHeight > max_height) {
                        max_height = textarea.scrollHeight;
                    }
                });
                var max_client_height =
                    $(window).height() - $(".modal-content").height();
                var new_height = Math.min(max_height, max_client_height);
                textareas.css({minHeight: new_height});
            }
        },
        set_maxlength: function() {
            // Set maxlength if initial field has size attr
            _.each(
                this.translatable_fields,
                function(field, name) {
                    var size = $("[name=" + name + "]")[0].maxLength;
                    if (size > 0) {
                        this.$(
                            'input.oe_translation_field[name$="' +
                                name +
                                '"], textarea.oe_translation_field[name$="' +
                                name +
                                '"]'
                        ).attr("maxlength", size);
                    }
                },
                this
            );
        },
        initialize_html_fields: function(lang) {
            // Initialize summernote if HTML field
            this.$(
                '.oe_form_field_html .oe_translation_field[name^="' + lang + '-"]'
            ).each(function() {
                var $parent = $(this)
                    .summernote({
                        focus: false,
                        toolbar: [
                            ["style", ["style"]],
                            ["font", ["bold", "italic", "underline", "clear"]],
                            ["fontsize", ["fontsize"]],
                            ["color", ["color"]],
                            ["para", ["ul", "ol", "paragraph"]],
                            ["table", ["table"]],
                            ["insert", ["link", "picture"]],
                            ["misc", ["codeview"]],
                            ["history", ["undo", "redo"]],
                        ],
                        prettifyHtml: false,
                        styleWithSpan: false,
                        inlinemedia: ["p"],
                        lang: "odoo",
                        onChange: function(value) {
                            $(this).toggleClass(
                                "touched",
                                value !== $(this).attr("data-value")
                            );
                        },
                    })
                    .parent();
                // Triggers a mouseup to refresh the editor toolbar
                $parent.find(".note-editable").trigger("mouseup");
                $parent.find(".note-editing-area").css({
                    minHeight: "100px",
                    minWidth: "260px",
                });
            });
        },
        set_fields_values: function(lang, tr_value) {
            _.each(
                tr_value,
                function(translation, field) {
                    this.$('.oe_translation_field[name="' + lang + "-" + field + '"]')
                        .val(translation || "")
                        .attr("data-value", translation || "");
                },
                this
            );
            this.initialize_html_fields(lang);
        },
        do_load_fields_values: function() {
            var self = this,
                deferred = [];

            this.$(".oe_translation_field")
                .val("")
                .removeClass("touched");
            var translatable_fields = [];
            _.forEach(this.translatable_fields, function(field, name) {
                translatable_fields.push(name);
            });

            var def = $.Deferred();
            deferred.push(def);
            rpc.query({
                model: this.model,
                method: "get_field_translations",
                args: [[this.res_id]],
                kwargs: {
                    field_names: translatable_fields,
                },
            }).then(function(res) {
                if (res[self.res_id]) {
                    _.each(res[self.res_id], function(translation, lang) {
                        self.set_fields_values(lang, translation);
                    });
                    self.resize_textareas();
                    self.set_maxlength();
                    def.resolve();
                }
            });

            return deferred;
        },
        on_button_save: function() {
            var translations = {},
                self = this,
                save_mutex = new Mutex();
            this.$(".oe_translation_field.touched").each(function() {
                var field = $(this)
                    .attr("name")
                    .split("-");
                if (!translations[field[0]]) {
                    translations[field[0]] = {};
                }
                translations[field[0]][field[1]] = $(this).val();
            });
            _.each(translations, function(text, code) {
                save_mutex.exec(function() {
                    var done = new $.Deferred();

                    var context = new Context(session.user_context, {lang: code});
                    rpc.query({
                        model: self.model,
                        method: "write",
                        args: [self.res_id, text],
                        kwargs: {context: context.eval()},
                    }).then(function() {
                        done.resolve();
                    });
                    if (code === self.view_language) {
                        var changes = {};
                        _.each(text, function(value, key) {
                            changes[key] = value;
                        });
                        self.trigger_up("field_changed", {
                            dataPointID: self.record_id,
                            changes: changes,
                        });
                    }
                    return done;
                });
            });
            save_mutex.exec(function() {
                self.view.reload();
            });
            this.close();
        },
        on_button_close: function() {
            this.close();
        },
    });

    FormController.include({
        renderSidebar: function($node) {
            this._super($node);
            if (this.sidebar) {
                var item = this.is_action_enabled("edit") && {
                    label: _t("Translate"),
                    callback: this.on_button_translate,
                };
                if (item) {
                    this.sidebar.items.other.push(item);
                }
            }
        },
        on_button_translate: function() {
            var self = this;
            $.when(this.has_been_loaded).then(function() {
                self.open_translate_dialog(null, self.initialState.res_id);
            });
        },
    });

    BasicController.include({
        open_translate_dialog: function(field, res_id) {
            new TranslateDialog(this, {field: field, res_id: res_id}).open();
        },

        _onTranslate: function(event) {
            // The image next to the fields opens the translate dialog
            event.stopPropagation();
            var self = this;
            var record = this.model.get(event.data.id, {raw: true});
            this._rpc({
                route: "/web/dataset/call_button",
                params: {
                    model: "ir.translation",
                    method: "translate_fields",
                    args: [record.model, record.res_id, event.data.fieldName],
                    kwargs: {context: record.getContext()},
                },
            }).then(function() {
                var res_id = event.target.res_id
                    ? event.target.res_id
                    : event.target.state.res_id;
                self.open_translate_dialog(event.data, res_id);
            });
        },
    });

    return {
        TranslateDialog: TranslateDialog,
    };
});
